
# This Makefile requires GNU make. Really.

SHELL = /bin/sh

# Package and host information.

name    = @PACKAGE_NAME@
version = @PACKAGE_VERSION@
dist    = $(name)-$(version)

host    = @host@

# Source and installation paths.

srcdir      = @srcdir@
VPATH       = @srcdir@

prefix      = @prefix@
exec_prefix = @exec_prefix@
datarootdir = @datarootdir@

bindir      = @bindir@
includedir  = @includedir@
libdir      = @libdir@
datadir     = @datadir@
mandir      = @mandir@
man1dir     = $(mandir)/man1

pkgconfigdir = $(libdir)/pkgconfig

# Staging directory for 'make install'.

DESTDIR=

# OS-specific special filename extensions. configure tries to guess this, but
# if it guesses wrong, you can set these as needed.

EXE=@EXEEXT@
DLL=@DLLEXT@

# Programs.

CC = @CC@
CXX = @CXX@
INSTALL = @INSTALL@
FLEX = @FLEX@
BISON = @BISON@
EMACS = @EMACS@

# Linker flags and required libraries. These are determined automatically by
# configure, but if necessary you can also change these on the command line.

LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
LIBOBJS = @LIBOBJS@

# Compilation flags.

LLVM_FLAGS = @LLVM_FLAGS@
LLVM_LDFLAGS = @LLVM_LDFLAGS@
LLVM_LIBS = @LLVM_LIBS@
LLVM_EXE_LIBS = @LLVM_EXE_LIBS@

RL_LIBS  = @RL_LIBS@

CPPFLAGS = @CPPFLAGS@
CFLAGS   = @CFLAGS@
CXXFLAGS = @CXXFLAGS@

# See whether emacs is installed and try to guess its installation prefix. If
# this guesses wrong, you can specify the absolute path to emacs manually by
# setting the EMACS variable accordingly. In either case, if EMACS is set then
# pure-mode.el will be byte-compiled and installed automatically. You can also
# set the elispdir variable if you need to specify a custom location for the
# elisp files.

emacs_prefix = $(patsubst %/bin/emacs,%,$(EMACS))
ifeq ($(strip $(emacs_prefix)),)
# Fall back to $(prefix).
emacs_prefix = $(prefix)
endif
elispdir = $(emacs_prefix)/share/emacs/site-lisp
ifeq ($(strip $(EMACS)),)
EMACS = emacs
else
elcfiles = @elcfiles@
endif

# Location of the Pure library directory. Depends on whether we're doing a
# versioned install. This enables you to install different versions of the
# Pure interpreter on the same system. Versioning is disabled by default, you
# can enable it by setting 'versioned' to 'yes', or by running configure with
# --enable-versioned.

versioned = @versioned@

purelib_base = $(name)
ifeq ($(versioned), yes)
purelib_vers = $(purelib_base)-$(version)
else
purelib_vers = $(purelib_base)
endif

AUXDEFS = -DPURELIB='"$(libdir)/$(purelib_vers)"'

# Pure library name. As of Pure 0.21, we use the standard $(major).$(minor)
# versioning scheme, which is independent of the Pure version number and the
# $(versioned) flag. Following customary practices supported by most modern
# operating systems, the $(major) version number gets incremented only when
# the runtime ABI changes, and the $(minor) version number is used to indicate
# bugfix releases.

major = 8
minor = 0

libpure_name    = $(name)
libpure_lnkname = lib$(libpure_name)$(DLL)
libpure_soname  = lib$(libpure_name)$(DLL).$(major)
libpure         = lib$(libpure_name)$(DLL).$(major).$(minor)

# Whether to build the Pure runtime library. If this is set to anything but
# "yes", the interpreter is linked statically and no separate library is
# produced. This is necessary on some systems where LLVM cannot be linked in
# dynamically.

sharedlib = @sharedlib@

# Auxiliary libraries to be loaded at runtime. Usually this is just libpure
# (when built), but on some systems we have to load additional dlls to resolve
# some library functions.

ifeq ($(sharedlib), yes)
AUXLIBS = -DLIBDIR='"$(libdir)"' -DLIBPURE='"$(libpure_soname)"'
endif

# Other platform-specific defaults, edit this as needed. XXXFIXME: This is a
# big mess, mostly due to differences in the way shared libraries are
# handled. Please report changes needed for systems not supported here.

# Generic defaults for gcc/elf-based systems.

PIC = @PIC@
shared = @shared@

soname = -Wl,-soname,$(libpure_soname)
LD_LIB_PATH = @LD_LIB_PATH@

# Take care of some common systems.

# Windows
ifneq "$(findstring -mingw,$(host))" ""
libpure_soname = lib$(libpure_name)$(major)$(DLL)
libpure = lib$(libpure_name)$(major)$(DLL)
LDFLAGS = -Wl,--stack=0x800000 -Wl,--enable-auto-import
AUXLIBS += -DLIBGLOB='"libglob.dll"' -DLIBREGEX='"libgnurx-0.dll"'
LIBS += -lmingwex
endif

# OSX
ifneq "$(findstring -darwin,$(host))" ""
# OSX uses a slightly different library naming scheme, and sonames are handled
# in a different way.
libpure_soname = lib$(libpure_name).$(major)$(DLL)
libpure = lib$(libpure_name).$(major).$(minor)$(DLL)
soname = -install_name $(libdir)/$(libpure_soname) -compatibility_version $(major) -current_version $(major).$(minor)
endif

# No need to edit below this line. Unless you really have to. :) ############

SOURCE = expr.cc expr.hh funcall.h gsl_structs.h interpreter.cc interpreter.hh \
lexer.ll lexerdefs.hh matcher.cc matcher.hh parser.yy parserdefs.hh \
printer.cc printer.hh runtime.cc runtime.h symtable.cc symtable.hh \
util.cc util.hh
EXTRA_SOURCE = lexer.cc parser.cc parser.hh location.hh position.hh stack.hh
OBJECT = $(subst .cc,.o,$(filter %.cc,$(SOURCE) $(EXTRA_SOURCE))) $(LIBOBJS)

DISTFILES = COPYING COPYING.LESSER COPYING.LLVM \
ChangeLog INSTALL NEWS README TODO \
Makefile.in acinclude.m4 aclocal.m4 configure.ac configure config.h.in \
config/config.guess config/config.sub config/install-sh \
$(SOURCE) $(EXTRA_SOURCE) w3centities.c strptime.c pure.cc pure_norl.cc \
pure_main.c pure.1 pure.txt puretut.txt install-docs.sh run-tests.in \
run-test.in pure.pc.in etc/pure-mode.el.in etc/pure.* etc/pure-highlight.lang \
debian/* \
examples/COPYING examples/Makefile.in examples/*.pure examples/*.purerc \
examples/*.c examples/*.f90 examples/libor/COPYING examples/libor/*.pure \
examples/bitcode/Makefile examples/bitcode/*.c examples/bitcode/*.f90 \
examples/bitcode/*.dsp examples/bitcode/*.pure \
examples/hellomod/Makefile examples/hellomod/*.c examples/hellomod/*.pure \
lib/*.pure test/*.pure test/*.log test/*.blob
# These need special editing (see dist target, datesubst below).
SEDFILES = INSTALL

.PHONY: all elc clean realclean depend install uninstall install-docs \
install-el install-elc uninstall-el uninstall-elc \
strip dist distcheck cleanlogs logs check config

# compilation

all: pure$(EXE) pure_main.o etc/pure-mode.el $(elcfiles)

ifeq ($(sharedlib), yes)
pure$(EXE): pure.o $(libpure)
	$(CXX) -o $@ -L. $(LDFLAGS) pure.o -l$(libpure_name) $(LLVM_EXE_LIBS) $(LLVM_LDFLAGS) $(LIBS) $(RL_LIBS)
else
pure$(EXE): pure.o $(OBJECT)
	$(CXX) -o $@ $(LDFLAGS) pure.o $(OBJECT) $(LLVM_LIBS) $(LLVM_LDFLAGS) $(LIBS) $(RL_LIBS)
endif

$(libpure): $(OBJECT)
	$(CXX) $(shared) $(soname) -o $@ $(LDFLAGS) $(OBJECT) $(LLVM_LIBS) $(LLVM_LDFLAGS) $(LIBS)
ifneq ($(libpure), $(libpure_soname))
	ln -sf $(libpure) $(libpure_soname)
endif
ifneq ($(libpure), $(libpure_lnkname))
	ln -sf $(libpure) $(libpure_lnkname)
endif

pure.o: pure.cc
	$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LLVM_FLAGS) -I. -I$(srcdir) $(AUXDEFS) -c -o $@ $<

runtime.o: runtime.cc
	$(CXX) $(CXXFLAGS) $(PIC) $(CPPFLAGS) $(LLVM_FLAGS) -I. -I$(srcdir) $(AUXDEFS) -c -o $@ $<

interpreter.o: interpreter.cc
	$(CXX) $(CXXFLAGS) $(PIC) $(CPPFLAGS) $(LLVM_FLAGS) -I. -I$(srcdir) $(AUXLIBS) -c -o $@ $<

%.o: %.cc
	$(CXX) $(CXXFLAGS) $(PIC) $(CPPFLAGS) $(LLVM_FLAGS) -I. -I$(srcdir) -c -o $@ $<

$(srcdir)/lexer.cc: lexer.ll
	$(FLEX) -o $(srcdir)/lexer.cc $<

$(srcdir)/parser.cc: parser.yy
	$(BISON) -v -o $(srcdir)/parser.cc $<

parser.hh location.hh position.hh stack.hh: parser.cc

# create pure-mode.el from pure-mode.el.in

etc/pure-mode.el: Makefile etc/pure-mode.el.in
	rm -f etc/pure-mode.el etc/pure-mode.el.tmp
	test -d etc || mkdir etc
	sed -e 's,@bindir\@,$(bindir),g' -e 's,@libdir\@,$(libdir),g' $(srcdir)/etc/pure-mode.el.in > etc/pure-mode.el.tmp
	mv etc/pure-mode.el.tmp etc/pure-mode.el

# create pure-mode.elc from pure-mode.el (this requires emacs)

ELC = $(EMACS) -q --no-site-file -batch -eval "(add-to-list 'load-path \".\")" -eval "(setq byte-compile-warnings '(callargs free-vars noruntime redefine))" -f batch-byte-compile

etc/pure-mode.elc: etc/pure-mode.el
	cd etc && $(ELC) pure-mode.el

elc: etc/pure-mode.elc

# generate the library documentation (this requires pure-doc)

# make sure to get these into the right order
libsources = prelude.pure strings.pure matrices.pure records.pure \
primitives.pure pointers.pure math.pure array.pure heap.pure \
dict.pure set.pure system.pure regex.pure posix.pure getopt.pure
libfiles = $(addprefix $(srcdir)/lib/, $(libsources))

purelib.txt: $(libfiles)
	pure-doc $(libfiles) > $@

install.txt: INSTALL
	ln -sf $< $@

# cleaning

clean:
	rm -f *~ *.bak pure$(EXE) $(OBJECT) pure.o pure_main.o $(libpure_lnkname) $(libpure_soname) $(libpure) parser.output etc/pure-mode.elc

distclean: clean
	rm -f Makefile config.h config.log config.status etc/pure-mode.el $(dist).tar.gz

realclean: distclean
	rm -f $(addprefix $(srcdir)/, $(EXTRA_SOURCE))

# dependencies (rerun configure after this)

depend: $(SOURCE) $(EXTRA_SOURCE)
	(cd $(srcdir) && makedepend -f Makefile.in -Y pure.cc $(SOURCE) $(EXTRA_SOURCE) 2> /dev/null)

# regenerate configure et al

config:
	cd '$(srcdir)' && autoreconf

Makefile: Makefile.in config.status
	./config.status

config.status: configure
	./config.status --recheck

$(srcdir)/configure: configure.ac acinclude.m4
	cd '$(srcdir)' && autoreconf

# installation

ifeq ($(versioned), yes)
pure_includedir = $(includedir)/pure-$(version)
pure_libdir = $(libdir)/pure-$(version)
pure_exe = pure-$(version)$(EXE)
pure_pc = pure-$(version).pc
pure_1 = pure-$(version).1
else
pure_includedir = $(includedir)/pure
pure_libdir = $(libdir)/pure
pure_exe = pure$(EXE)
pure_pc = pure.pc
pure_1 = pure.1
endif

install: pure$(EXE) pure.1
ifeq ($(versioned), yes)
	rm -rf $(addprefix $(DESTDIR), $(includedir)/pure $(libdir)/pure)
endif
	for x in $(addprefix $(DESTDIR), $(bindir) $(pkgconfigdir) $(pure_includedir) $(pure_libdir) $(man1dir)); do $(INSTALL) -d $$x; done
ifeq ($(sharedlib), yes)
	$(INSTALL) $(libpure) $(DESTDIR)$(libdir)/$(libpure)
ifneq ($(libpure), $(libpure_soname))
	ln -sf $(libdir)/$(libpure) $(DESTDIR)$(libdir)/$(libpure_soname)
endif
ifneq ($(libpure), $(libpure_lnkname))
	ln -sf $(libdir)/$(libpure) $(DESTDIR)$(libdir)/$(libpure_lnkname)
endif
endif
	$(INSTALL) pure$(EXE) $(DESTDIR)$(bindir)/$(pure_exe)
	$(INSTALL) -m 644 pure.pc $(DESTDIR)$(pkgconfigdir)/$(pure_pc)
	$(INSTALL) -m 644 $(srcdir)/runtime.h $(DESTDIR)$(pure_includedir)
	$(INSTALL) -m 644 $(srcdir)/pure_main.c pure_main.o $(DESTDIR)$(pure_libdir)
	for x in $(srcdir)/lib/*.pure; do $(INSTALL) -m 644 $$x $(DESTDIR)$(pure_libdir); done
	$(INSTALL) -m 644 $(srcdir)/pure.1 $(DESTDIR)$(man1dir)/$(pure_1)
ifneq ($(elcfiles),)
	$(INSTALL) -d $(DESTDIR)$(elispdir)
	$(INSTALL) -m 644 etc/pure-mode.el etc/pure-mode.elc $(DESTDIR)$(elispdir)
endif
ifeq ($(versioned), yes)
	ln -sf $(bindir)/$(pure_exe) $(DESTDIR)$(bindir)/pure$(EXE)
	ln -sf $(pkgconfigdir)/$(pure_pc) $(DESTDIR)$(pkgconfigdir)/pure.pc
	ln -sf $(pure_includedir) $(DESTDIR)$(includedir)/pure
	ln -sf $(pure_libdir) $(DESTDIR)$(libdir)/pure
	ln -sf $(man1dir)/$(pure_1) $(DESTDIR)$(man1dir)/pure.1
endif

uninstall:
	rm -rf $(addprefix $(DESTDIR), $(bindir)/pure$(EXE) $(pkgconfigdir)/pure.pc $(libdir)/$(libpure_lnkname) $(libdir)/$(libpure_soname) $(libdir)/$(libpure) $(includedir)/pure $(libdir)/pure $(man1dir)/pure.1 $(elispdir)/pure-mode.el $(elispdir)/pure-mode.elc)
ifeq ($(versioned), yes)
	rm -rf $(addprefix $(DESTDIR), $(bindir)/$(pure_exe) $(pkgconfigdir)/$(pure_pc) $(pure_includedir) $(pure_libdir) $(man1dir)/$(pure_1))
endif

# install the online documentation (requires wget)

# you can set this on the command line to point 'install-docs' to an
# alternative url or a local file:
docs = http://pure-lang.googlecode.com/files/pure-docs-$(version).tar.gz

# old version to try if the current version has not been released yet
oldvers = $(shell echo $(version) | awk -F. '{ printf("%d.%d\n", $$1,$$2-1); }')
olddocs = http://pure-lang.googlecode.com/files/pure-docs-$(oldvers).tar.gz

install-docs:
	@MAKE=$(MAKE) ./install-docs.sh "$(docs)" || MAKE=$(MAKE) ./install-docs.sh "$(olddocs)"

# install pure-mode.el and pure-mode.elc

# This will normally be done automatically with 'make install' if emacs is
# detected on your system. However, these targets also allow you to do this
# manually, e.g., if emacs is installed in an unusual location, or if you want
# to install the files in a custom location (in the latter case you will also
# want to set elispdir accordingly).

install-el: etc/pure-mode.el
	$(INSTALL) -d $(DESTDIR)$(elispdir)
	$(INSTALL) -m 644 $< $(DESTDIR)$(elispdir)

install-elc: etc/pure-mode.elc
	$(INSTALL) -d $(DESTDIR)$(elispdir)
	$(INSTALL) -m 644 $< $(DESTDIR)$(elispdir)

uninstall-el:
	rm -rf $(DESTDIR)$(elispdir)/pure-mode.el

uninstall-elc:
	rm -rf $(DESTDIR)$(elispdir)/pure-mode.elc

# roll a distribution tarball

date = $(shell date "+%B %-d, %Y")
datesubst = sed -e "s?@version@?$(version)?g" -e "s?|today|?$(date)?g" < $(1) > $(2)

distdirs = config debian etc examples examples/bitcode examples/hellomod examples/libor lib test
dist: $(addprefix $(srcdir)/, $(filter-out test/%.log, $(DISTFILES)))
	rm -rf $(dist)
	mkdir $(dist)
	for d in $(distdirs); do mkdir $(dist)/$$d || exit 1; done
	(builddir=$$PWD; cd $(srcdir); for x in $(DISTFILES); do ln -sf $$PWD/$$x $$builddir/$(dist)/$$x; done; for x in $(SEDFILES); do rm -f $$builddir/$(dist)/$$x; $(call datesubst,$$PWD/$$x,$$builddir/$(dist)/$$x); done)
	rm -f $(dist).tar.gz
	tar cfzh $(dist).tar.gz $(dist)
	rm -rf $(dist)

distcheck: dist
	tar xfz $(dist).tar.gz
	cd $(dist) \
	  && ./configure $(DISTCHECK_CONFIGURE_FLAGS) \
	  && $(MAKE) \
	  && $(MAKE) check \
	  && $(MAKE) install DESTDIR=./BUILD
	rm -rf $(dist)

# create a Debian package (this requires special tools like debuild)

# NOTE: It is assumed that the source tarball for the current version is
# available in the project download area, in which case it will be downloaded
# and renamed to something like pure_$(version).orig.tar.gz which is what the
# Debian tools look for. Otherwise you'll have to provide a suitable source
# tarball yourself and place it into the build directory. The easiest way to
# do this is to just roll a distribution tarball using 'make dist' and rename
# it appropriately.

# By default, running this target (as 'make deb') will build binary packages
# which you'll have to sign with your PGP key. You can change this by setting
# the DEBUILD_FLAGS variable accordingly (e.g., 'make deb DEBUILD_FLAGS=-S'
# will only create the source package, adding '-us -uc' skips the signing
# step, etc.). See debuild(1) for details.

# If you're running this from repository sources, it will create a Debian
# package from these, with the appropriate patches against the release
# tarball. In this case, maintainers should update debian/changelog
# accordingly. If there is no corresponding release tarball (usually because
# the version number has been bumped), you'll have to provide a corresponding
# .orig tarball yourself (see above). In this case it is a good idea to pick a
# version number which clearly indicates that the package was built from
# repository sources.

# name of the pristine tarball
debsrc = $(shell echo $(dist) | sed -e 's/-$(version)/_$(version)/').orig.tar.gz

deb: $(debsrc) dist
	tar xfz $(dist).tar.gz
	cd $(dist) && debuild $(DEBUILD_FLAGS)
	rm -rf $(dist)

# grab the pristine tarball
$(debsrc):
	wget -nv http://pure-lang.googlecode.com/files/$(dist).tar.gz -O $@

# test logs, make check

tests = $(wildcard $(srcdir)/test/test*.pure)
logs  = $(srcdir)/test/prelude.log $(srcdir)/test/special.log $(tests:.pure=.log)

logs: $(logs)

cleanlogs:
	rm -f $(srcdir)/test/*.log

$(srcdir)/test/prelude.log: lib/prelude.pure lib/primitives.pure lib/matrices.pure lib/records.pure lib/strings.pure
	./run-test -n < $< > $@ 2>&1

$(srcdir)/test/special.log: test/special.pure lib/*.pure
	./run-test  < $< > $@ 2>&1

%.log: %.pure
	./run-test  < $< > $@ 2>&1

check: pure
	./run-tests

recheck: pure
	./run-tests -f

# DO NOT DELETE

pure.o: interpreter.hh config.h expr.hh matcher.hh runtime.h symtable.hh
pure.o: printer.hh parserdefs.hh parser.hh stack.hh util.hh location.hh
pure.o: position.hh
expr.o: expr.hh interpreter.hh config.h matcher.hh runtime.h symtable.hh
expr.o: printer.hh parserdefs.hh parser.hh stack.hh util.hh location.hh
expr.o: position.hh
interpreter.o: interpreter.hh config.h expr.hh matcher.hh runtime.h
interpreter.o: symtable.hh printer.hh parserdefs.hh parser.hh stack.hh
interpreter.o: util.hh location.hh position.hh gsl_structs.h
interpreter.o: config.h expr.hh matcher.hh runtime.h symtable.hh printer.hh
interpreter.o: parserdefs.hh parser.hh stack.hh util.hh location.hh
interpreter.o: position.hh
lexer.o: interpreter.hh config.h expr.hh matcher.hh runtime.h symtable.hh
lexer.o: printer.hh parserdefs.hh parser.hh stack.hh util.hh location.hh
lexer.o: position.hh lexerdefs.hh
lexerdefs.o: parserdefs.hh expr.hh parser.hh stack.hh printer.hh matcher.hh
lexerdefs.o: runtime.h util.hh location.hh position.hh
matcher.o: matcher.hh expr.hh runtime.h interpreter.hh config.h symtable.hh
matcher.o: printer.hh parserdefs.hh parser.hh stack.hh util.hh location.hh
matcher.o: position.hh
matcher.o: expr.hh runtime.h
parser.o: parserdefs.hh expr.hh printer.hh matcher.hh runtime.h util.hh
parser.o: lexerdefs.hh parser.hh stack.hh location.hh position.hh
parser.o: interpreter.hh config.h symtable.hh
parserdefs.o: expr.hh
printer.o: printer.hh expr.hh matcher.hh runtime.h interpreter.hh config.h
printer.o: symtable.hh parserdefs.hh parser.hh stack.hh util.hh location.hh
printer.o: position.hh gsl_structs.h
printer.o: expr.hh matcher.hh runtime.h
runtime.o: runtime.h expr.hh interpreter.hh config.h matcher.hh symtable.hh
runtime.o: printer.hh parserdefs.hh parser.hh stack.hh util.hh location.hh
runtime.o: position.hh funcall.h gsl_structs.h
symtable.o: symtable.hh expr.hh printer.hh matcher.hh runtime.h util.hh
symtable.o: expr.hh printer.hh matcher.hh runtime.h
util.o: util.hh config.h w3centities.c
lexer.o: interpreter.hh config.h expr.hh matcher.hh runtime.h symtable.hh
lexer.o: printer.hh parserdefs.hh parser.hh stack.hh util.hh location.hh
lexer.o: position.hh lexerdefs.hh
parser.o: parser.hh stack.hh parserdefs.hh expr.hh printer.hh matcher.hh
parser.o: runtime.h util.hh location.hh position.hh lexerdefs.hh
parser.o: interpreter.hh config.h symtable.hh
parser.o: stack.hh parserdefs.hh expr.hh printer.hh matcher.hh runtime.h
parser.o: util.hh location.hh position.hh
location.o: position.hh
